﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Collections;
using System.Windows.Forms;
using NetChatInterface;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Runtime.Serialization;

namespace NetChatInterface
{


    public static class DataTransfer
    {
        [Serializable]

       [StructLayoutAttribute(LayoutKind.Sequential,CharSet=CharSet.Ansi,Pack=1)]

      public  struct transfer_message
        {
            public string IP;

            public int msg;

            public string entity;
        }
        //static byte[] StructToBytes(transfer_message structObj)
        //{
        //    int size = Marshal.SizeOf(structObj);
        //    IntPtr buffer = Marshal.AllocHGlobal(size);
        //    try
        //    {
        //        Marshal.StructureToPtr(structObj, buffer, false);
        //        byte[] bytes = new byte[size];
        //        Marshal.Copy(buffer, bytes, 0, size);
        //        return bytes;
        //    }
        //    finally
        //    {
        //        Marshal.FreeHGlobal(buffer);
        //    }

        //}

        //static transfer_message BytesToStruct(byte[] bytes, transfer_message structType)
        //{
        //    int size = Marshal.SizeOf(structType);

        //    if (size > bytes.Length)
        //    {
        //        //返回空
        //        return null;
        //    }

        //    IntPtr buffer = Marshal.AllocHGlobal(size);
        //    try
        //    {
        //        Marshal.Copy(bytes, 0, buffer, size);
        //        return (transfer_message)Marshal.PtrToStructure(buffer,typeof(structType));
        //    }

        //    finally
        //    {
        //        Marshal.FreeHGlobal(buffer);

        //    }
        //}



        private static UdpClient udp = new UdpClient(2007);//里面的端口号随意

        private static IPEndPoint remoteEndPoint;


        public static void receive()//在主程序里面+个后台线程来运行该方法
        {

            int m_intSerial = 0;
            int m_intBlocks = 0; //数据分割块数   
            int m_intLength = 0; //数据长度   
            int m_intMessageLength = 0;
            int place = 0;
            int m_intGetCount = 0;   


            while (true)//用死循环来监听发的数据包
            {
                remoteEndPoint = new IPEndPoint(new IPAddress(0), 0);

                byte[] bytesF = udp.Receive(ref remoteEndPoint);

                place = 0;
                m_intSerial = BitConverter.ToInt32(bytesF, place);
                place += 4;
                m_intBlocks = BitConverter.ToInt32(bytesF, place);
                place += 4;
                m_intLength = BitConverter.ToInt32(bytesF, place);
                place += 4;
                m_intMessageLength = BitConverter.ToInt32(bytesF, place);
                place += 4;

                byte[] data = new byte[m_intMessageLength]; //申明数据的总长   

                Array.Copy(bytesF, 16, data, m_intBlockLength * m_intSerial, m_intLength); //复制数据   

                m_intGetCount = m_intGetCount + 1;
                Application.DoEvents();

                if (m_intBlocks > 1)
                {
                    while (true)
                    {
                        byte[] bytes = udp.Receive(ref remoteEndPoint);

                        place = 0;
                        m_intSerial = BitConverter.ToInt32(bytes, place);
                        place += 4;
                        m_intBlocks = BitConverter.ToInt32(bytes, place);
                        place += 4;
                        m_intLength = BitConverter.ToInt32(bytes, place);
                        place += 4;
                        m_intMessageLength = BitConverter.ToInt32(bytes, place);
                        place += 4;

                        Array.Copy(bytes, 16, data, m_intBlockLength * m_intSerial, m_intLength); //复制数据   

                        m_intGetCount = m_intGetCount + 1;

                        Application.DoEvents();

                        if (m_intGetCount >= m_intBlocks)
                        {
                            break;
                        }
                    }
                }

                //MessageBox.Show(data.ToString());

                //return;


               transfer_message receive_message = new transfer_message();

               //receive_message= BytesToStruct(data, receive_message);

               BinaryFormatter formatter = new BinaryFormatter();

               MemoryStream stream = new MemoryStream(data);

               receive_message = (transfer_message)formatter.Deserialize(stream); 

                int i = 0;
                try
                {
                    do
                    {

                        if (receive_message.IP == MainForm.identity[i].IP)
                        {
                            MessageImport.PostMessage(MainForm.identity[i].Handle, receive_message.msg, 0, Marshal.StringToHGlobalAnsi(receive_message.entity));

                            break;
                        }

                        i++;

                    } while (MainForm.identity[i].IP != "");
                }
                catch (System.Exception e)
                {
                    //MessageBox.Show(e.ToString());
                }

                stream.Close();
            }
        }


        private static UdpClient client = new UdpClient(); //客户端

        private static IPEndPoint serverIP;

        private  static int   m_intBlockLength =   1000; //每一个数据包的大小  

       //private static System.IO.MemoryStream memStream = new System.IO.MemoryStream();


        public static void send(string IP, int msg, string entity)//下面的端口是发到服务器上的,要和Server监听的端口一致
        {

            serverIP = new IPEndPoint(IPAddress.Parse(IP), 2007); //服务器IP

            string strHostName = Dns.GetHostName(); //得到本机的主机名
            IPHostEntry ipEntry = Dns.GetHostByName(strHostName); //取得本机IP
            string strAddr = ipEntry.AddressList[0].ToString();

            transfer_message send_message = new transfer_message();

            send_message.IP = strAddr;

            send_message.msg = msg;

            send_message.entity = entity;

            //Byte[] mybyte = StructToBytes(send_message);

            IFormatter temp = new BinaryFormatter();

            MemoryStream memStream = new MemoryStream();

            temp.Serialize(memStream, send_message);

            byte[] mybyte = memStream.ToArray();

            //memStream.Read(mybyte, 0, 100);

            //memStream.Position = 0; 

            int   m_intMessageLength   =   mybyte.Length;   
            int   m_intSerial   =   0;   

            int   m_intBlocks =   Convert.ToInt32(Math.Ceiling(Convert.ToDouble(m_intMessageLength)/Convert.ToDouble(m_intBlockLength))); //数据分割块数   

            while   (m_intMessageLength   >   0)   
            {   
            try     
            {   
            int   m_intLength =   m_intBlockLength; //数据长度   

            if   (m_intMessageLength < m_intLength)   
            {   
            m_intLength   =   m_intMessageLength;   
            }   

            byte[]   data   =   new   byte[m_intLength+16];   

            int   place   =   0;   
            Buffer.BlockCopy(BitConverter.GetBytes(m_intSerial),   0,   data,place,4); //顺序戳   
            place   +=   4;   
            Buffer.BlockCopy(BitConverter.GetBytes(m_intBlocks),   0,   data,place,4); //数据总块数   
            place   +=   4;   
            Buffer.BlockCopy(BitConverter.GetBytes(m_intLength),   0,   data,place,4); //数据长度   
            place   +=   4;   
            Buffer.BlockCopy(BitConverter.GetBytes(mybyte.Length),   0,   data,place,4); //数据总长度   
            place   +=   4;   
            Array.Copy(mybyte,   m_intSerial   *   1000,   data,   16,   m_intLength); //复制数据   


            client.Send(data, data.Length, serverIP);

            m_intSerial = m_intSerial + 1;
            m_intMessageLength = m_intMessageLength - m_intLength;
            }
            catch (System.Exception pe)
            {
                Console.WriteLine(pe.ToString());
            }
      
            }
            memStream.Close();

        }

    }

}